package org.sws.domain.strategy.service.armory;

import org.sws.domain.activity.model.entity.ActivityEntity;
import org.sws.domain.activity.repository.IActivityRepository;
import org.sws.domain.strategy.model.entity.StrategyAwardEntity;
import org.sws.domain.strategy.model.entity.StrategyEntity;
import org.sws.domain.strategy.model.entity.StrategyRuleEntity;
import org.sws.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import org.sws.domain.strategy.repository.IStrategyRepository;
import org.sws.types.common.Constants;
import org.sws.types.enums.ResponseCode;
import org.sws.types.exception.AppException;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Author sws
 * @Date 2025/4/23 09:17
 * @description:
 */
public abstract class AbstractStrategyAlgorithm  implements IStrategyArmory,IStrategyDispatch{
    @Resource
    protected IStrategyRepository strategyRepository;
    @Resource
    private IActivityRepository activityRepository;

    @Override
    public void assembleLotteryStrategyByActivityId(Long activityId) {
        // 根据活动id 查询策略id
        ActivityEntity activityEntity = activityRepository.queryRaffleActivityByActivityId(activityId);
        if (null == activityEntity) {
            throw new AppException(ResponseCode.ACTIVITY_NOT_EXIST.getCode(), ResponseCode.ACTIVITY_NOT_EXIST.getInfo());
        }
        assembleLotteryStrategy(activityEntity.getStrategyId());
    }
    @Override
    public Boolean assembleLotteryStrategy(Long strategyId) {
        // 1 查询策略下所有奖品配置
        List<StrategyAwardEntity> strategyAwardEntities = strategyRepository.queryStrategyAwardList(strategyId);
        if(strategyAwardEntities.isEmpty()){
            throw new AppException(ResponseCode.UN_ASSEMBLED_STRATEGY_ARMORY.getCode(), ResponseCode.UN_ASSEMBLED_STRATEGY_ARMORY.getInfo());
        }

        // 2 缓存奖品库存
        for (StrategyAwardEntity strategyAward : strategyAwardEntities) {
            Integer awardId = strategyAward.getAwardId();
            Integer awardCount = strategyAward.getAwardCount();
            cacheStrategyAwardCount(strategyId, awardId, awardCount);
        }

        // 3.1 默认抽奖（全量抽奖概率）
        armoryAlgorithm(String.valueOf(strategyId), strategyAwardEntities);

        // 3.2 权重策略配置 - 适用于 rule_weight 权重规则配置
        StrategyEntity strategyEntity = strategyRepository.queryStrategyEntityByStrategyId(strategyId);
        // 查询是否有权重这个选项的规则值配置
        String ruleWeight = strategyEntity.getRuleWeight();
        if (null == ruleWeight){
            return true;
        }
        // 查询营销的权重规则
        StrategyRuleEntity strategyRuleEntity = strategyRepository.queryStrategyRule(strategyId, ruleWeight);
        if (null == strategyRuleEntity) {
            throw new AppException(ResponseCode.STRATEGY_RULE_WEIGHT_IS_NULL.getCode(), ResponseCode.STRATEGY_RULE_WEIGHT_IS_NULL.getInfo());
        }
        // 得到策略是权重的规则值
        Map<String, List<Integer>> ruleWeightValueMap = strategyRuleEntity.getRuleWeightValues();
        Set<String> keys = ruleWeightValueMap.keySet();
        for (String key : keys) {
            List<Integer> ruleWeightValues = ruleWeightValueMap.get(key);
            // 深拷贝奖品配置集合
            ArrayList<StrategyAwardEntity> strategyAwardEntitiesClone = new ArrayList<>(strategyAwardEntities);
            // 根据权重移除权重下不存在的奖品
            strategyAwardEntitiesClone.removeIf(entity -> !ruleWeightValues.contains(entity.getAwardId()));
            // 装配奖品
            armoryAlgorithm(String.valueOf(strategyId).concat(Constants.UNDERLINE).concat(key), strategyAwardEntitiesClone);
        }
        return true;
    }

    /**
     * 装配奖品概率到redis
     * @param key 缓存key
     * @param strategyAwardEntities 奖品策略列表
     */
    protected abstract void armoryAlgorithm(String key, List<StrategyAwardEntity> strategyAwardEntities);

    /**
     * 转换计算，只根据小数位来计算。如【0.01返回100】、【0.009返回1000】、【0.0018返回10000】
     */
    protected BigDecimal convert(BigDecimal min){
        if (min.compareTo(BigDecimal.ZERO) == 0){
            return BigDecimal.ONE;
        }
        String minString = min.toString();
        // 小数点后位数
        String endValue = minString.substring(minString.indexOf(".") + 1);
        int endLength = 0;
        if (Double.parseDouble(endValue) > 0) {
            endLength = endValue.length();
        }
        return BigDecimal.valueOf(Math.pow(10, endLength));
    }

    /**
     * 缓存奖品库存
     * @param strategyId 策略ID
     * @param awardId 奖品ID
     * @param awardCount 奖品库存
     */
    private void cacheStrategyAwardCount(Long strategyId, Integer awardId, Integer awardCount) {
        String cacheKey = Constants.RedisKey.STRATEGY_AWARD_STOCK_KEY + strategyId + Constants.UNDERLINE + awardId;
        strategyRepository.cacheStrategyAwardCount(cacheKey, awardCount);
    }

    @Override
    public Integer getRandomAwardId(Long strategyId){
        return dispatchAlgorithm(String.valueOf(strategyId));
    }

    @Override
    public Integer getRandomAwardId(Long strategyId, String ruleWeightValue) {
        String key = String.valueOf(strategyId).concat(Constants.UNDERLINE).concat(ruleWeightValue);
        return dispatchAlgorithm(key);

    }

    protected abstract Integer dispatchAlgorithm(String key);


    @Override
    public Boolean subtractionAwardStock(Long strategyId, Integer awardId, Date activityEndTime) {
        String cacheKey = Constants.RedisKey.STRATEGY_AWARD_STOCK_KEY + strategyId + Constants.UNDERLINE + awardId;
        return strategyRepository.subtractionAwardStock(cacheKey, activityEndTime);
    }

    @Override
    public void awardStockConsumeSendQueue(StrategyAwardStockKeyVO strategyAwardStockKeyVO) {
        strategyRepository.awardStockConsumeSendQueue(strategyAwardStockKeyVO);
    }


}
